<?php

declare(strict_types=1);

namespace App\Controller\Admin;

use App\Constants\ErrorCode;

use App\Model\Admin\Admin;
use App\Model\ChargeDetail;
use App\Model\ChargeOption;
use App\Model\Device;
use App\Model\DevicePort;
use App\Model\DevicePortErrLog;
use App\Model\DeviceSignalLog;
use App\Model\DistributorDevice;
use App\Model\Distributors;
use App\Model\Order;
use App\Model\Station;
use App\Services\DeviceService;
use App\Services\FileService;
use App\Services\Iot\IotService1 as IotService;
use GuzzleHttp\Client;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\Guzzle\CoroutineHandler;
use Hyperf\Guzzle\HandlerStackFactory;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Utils\ApplicationContext;
use Psr\Container\ContainerInterface;
use Hyperf\Redis\Redis;
use Hyperf\DbConnection\Db;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Trait\ResponseMsg;
use App\Model\Normal;
use Hyperf\Di\Annotation\Inject;
use App\Controller\AbstractController;
use PhpOffice\PhpSpreadsheet\IOFactory;

class DevicesController extends AbstractController
{
    use ResponseMsg;

    protected Redis $redis;
    protected Normal $normal;

    #[Inject]
    protected Device $device;

    #[Inject]
    protected Distributors $distributors;


    #[Inject]
    protected Admin $admin;

    // 在构造函数中注入ClientFactory
    private ClientFactory $clientFactory;

    private $tcpUri = 'http://39.106.226.249:9003';

    public function __construct()
    {
        $this->clientFactory = container()->get(ClientFactory::class);
        $this->redis = container()->get(Redis::class);
        $this->normal = container()->get(Normal::class);

    }

    /**设备列表
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getList(RequestInterface $request): ResponseInterface
    {
        try {
            $page = $request->inputs(['page', 'limit', 'time', 'inline', 'station_id', 'distributor_id', 'is_active', 'sn', 'channel', 'is_bind']);
            $page['info'] = $this->admin->getInfo($request);
            $query = $this->device->query();
            $query->with(['distributor' => function ($query) {
                $query->select('id', 'name'); // 只获取经销商id和name
            }]);
            $query->with(['station' => function ($query) {
                $query->select('id', 'name'); // 只获取经销商id和name
            }]);
            $query->with(['station.charge' => function ($query) {
                $query->select('id', 'name');
            }]);
            $query->with('port');
            $query->withCount('orders');
            $query->with(['device_profit' => function($query) {
                $query->select('device_id', DB::raw('SUM(profit) as total_profit'))
                    ->groupBy('device_id');
            }]);
            $query->where(function ($query) use ($page) {
                if ($page['sn']) {
                    $query->where('sn', $page['sn']);
                }
                if (isset($page['distributor_id']) && $page['distributor_id']) {
                    $distributor  = $this->distributors->find($page['distributor_id']);
                    if($distributor->level == 1){
                        $distributors = Distributors::where('parent_id', $distributor->id)
                            ->orWhere('id', $page['distributor_id'])->pluck('id');
                        $query->whereIn('distributor_id', $distributors);
                    }else{
                        $query->where('distributor_id', $page['distributor_id']);
                    }
                } else {
                    if (isset($page['info']['distributor_id'])) {
                        $distributor  = $this->distributors->find($page['info']['distributor_id']);
                        if($distributor->level == 1){
                            $distributors = Distributors::where('parent_id', $distributor->id)
                                ->orWhere('id', $page['info']['distributor_id'])->pluck('id');
                            $query->whereIn('distributor_id', $distributors);
                        }else{
                            $query->where('distributor_id', $page['info']['distributor_id']);
                        }
                    }
                }
                if ($page['channel']) {
                    $query->where('channel', $page['channel']);
                }
                if ($page['is_bind'] != '') {
                    if ($page['is_bind'] == 0) {
                        $query->where('station_id', 0);
                    } else {
                        $query->where('station_id', '>', 0);
                    }
                }
                if ($page['station_id']) {
                    $query->where('station_id', $page['station_id']);
                }
                if ($page['inline'] != '') {
                    $query->where('inline', $page['inline']);
                }
                if ($page['is_active'] != '') {
                    $query->where('is_active', $page['is_active']);
                }
                if (isset($page['time']) && is_array($page['time'])) {
                    $query->where('created_at', '>=', $page['time'][0]);
                    $query->where('created_at', '<=', $page['time'][1]);
                }
            });
            $data['total'] = $query->count();
            $data['list'] = $query->orderBy('id', 'desc')
                ->offset(($page['page'] - 1) * $page['limit'])
                ->limit($page['limit'])
                ->get();
            return $this->success($data);
        } catch (\Exception $e) {
            return $this->error($e->getMessage() . $e->getTraceAsString());
        }
    }

    /**批量修改俯冲参数
     * @param RequestInterface $request
     * @return ResponseInterface
     */
    public function batchPower(RequestInterface $request): ResponseInterface
    {
        $full_power_min = $request->input('full_power_min', 20);
        $full_charge_time = $request->input('full_charge_time', 30);
        try {
            $list = Device::where('inline', 1)->get();
            foreach ($list as $v) {
                $v->full_power_min = $full_power_min;
                $v->full_charge_time = $full_charge_time;
                $v->save();
                $v->updateParams();
            }
            return $this->success();
        } catch (\Exception $e) {
            return $this->error(1001, $e->getMessage());
        }
    }

    /**
     * 导入设备
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function batchCreate(RequestInterface $request): ResponseInterface
    {
        $file = $request->file('file');
        $distributor = $request->input('distributor_id');
        $channel = $request->input('channel');
        $station_id = $request->input('station_id');
        if (empty($channel)) {
            return $this->error(code: 1003, msg: '请选择通道数量');
        }
        if ($distributor == 'undefined') {
            $distributor = '';
        }
        $spreadsheet = IOFactory::load($file->getRealPath());
        // 选择第一个工作表
        $worksheet = $spreadsheet->getActiveSheet();
        // 获取最后一行和列
        $highestRow = $worksheet->getHighestRow();
        $highestColumn = $worksheet->getHighestColumn();
        $snExists = [];
        $iotSnExists = [];
        for ($row = 2; $row <= $highestRow; ++$row) {
            $rowData = [];
            for ($col = 'A'; $col <= $highestColumn; ++$col) {
                $rowData[] = $worksheet->getCell($col . $row)->getValue();
            }
            // 创建用户并插入数据库
            if ($rowData[0] && $rowData[1]) {
                if (str_contains((string)$rowData[1], '；')) {
                    $rowData[1] = explode('；', (string)$rowData[1]);
                } else {
                    $rowData[1] = explode(';', (string)$rowData[1]);
                }
                if (in_array($rowData[0], $snExists)) {
                    return $this->error(code: 1003, msg: '设备编号' . $rowData[0] . '在上传文件中重复');
                }

                if (in_array($rowData[1], $iotSnExists)) {
                    return $this->error(code: 1003, msg: '物联网编号' . $rowData[1] . '在上传文件中重复');
                }

                $snExists[] = $rowData[0];
                $iotSnExists[] = $rowData[1];
            }
        }

        Db::beginTransaction();
        // 读取数据并插入数据库
        try {
            for ($row = 2; $row <= $highestRow; ++$row) {
                $rowData = [];
                for ($col = 'A'; $col <= $highestColumn; ++$col) {
                    $rowData[] = $worksheet->getCell($col . $row)->getValue();
                }
                // 创建用户并插入数据库
                if ($rowData[0] && $rowData[1]) {
                    $device = new Device();
                    $device->channel = $channel;
                    if ($station_id) {
                        $device->station_id = $station_id;
                    }
                    if ($distributor) {
                        $device->distributor_id = $distributor;
                    }
                    $device->sn = $rowData[0];
                    if (str_contains((string)$rowData[1], '；')) {
                        $rowData[1] = explode('；', (string)$rowData[1]);
                    } else {
                        $rowData[1] = explode(';', (string)$rowData[1]);
                    }
                    $check = Device::where('sn', $rowData[0])
                        ->first();
                    if ($check) {
                        return $this->error(code: 1002, msg: '设备编号' . $rowData[0] . '已存在 请删除该数据重新上传');
                    }
                    $device->save();
                }
            }
            Db::commit();
            return $this->success(msg: '导入成功');
        } catch (\Exception $e) {
            Db::rollBack();
            return $this->error(code: 1002, msg: '导入失败，请检查文件内容是否符合规范' . $e->getMessage());
        }
    }

    /**生成二维码
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function qrCode(RequestInterface $request): ResponseInterface
    {
        $sn = $request->input('sn');
        $img = FileService::creatCode($sn);
        return $this->success($img);
    }

    /**修改状态
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function changeStatus(RequestInterface $request): ResponseInterface
    {
        $status = $request->input('status', 0, 'int');
        $id = $request->input('id', 0, 'int');
        if (!$id) {
            return $this->error(code: 1001, msg: '缺失参数id');
        }
        $this->device->where('id', $id)->update(['is_active' => $status]);
        return $this->success(msg: '修改成功');
    }

    /**创建
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function create(RequestInterface $request): \Psr\Http\Message\ResponseInterface
    {
        $data = $request->post();
        $info = $this->admin->getInfo($request);
        if (!isset($data['distributor_id']) || !$data['distributor_id']) {
            if (isset($info['distributor_id'])) {
                $data['distributor_id'] = $info['distributor_id'];
            }
        }
        if (!$data['distributor_id']) {
            $data['distributor_id'] = 0;
        }
        if(isset($data['station_id']) && !$data['station_id']){
            $data['station_id'] = 0;
        }
        if (array_key_exists('id', $data) && $data['id'] > 0) {
            $id = $data['id'];
            unset($data['id']);
            $check = Device::where('sn', $data['sn'])
                ->where('id', '<>', $id)
                ->count();
            if ($check) {
                return $this->error(1002, '已存在该设备编号');
            }
            $this->device->where('id', $id)->update($data);
        } else {
            $check = Device::where('sn', $data['sn'])
                ->count();
            if ($check) {
                return $this->error(1002, '已存在该设备编号');
            }
            Device::create($data);
        }
        return $this->success();
    }

    /**批量修改
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function batchChange(RequestInterface $request): \Psr\Http\Message\ResponseInterface
    {
        $page = $request->inputs(['ids', 'distributor_id', 'station_id', 'active_at', 'expires_at']);
        if (!is_array($page['ids'])) {
            $page['ids'] = json_decode($page['ids'], true);
        }
        if (isset($page['distributor_id']) && $page['distributor_id']) {
            $data['distributor_id'] = $page['distributor_id'];
        }
        if (isset($page['station_id']) && $page['station_id']) {
            $data['station_id'] = $page['station_id'];
        }
        if (isset($page['active_at']) && $page['active_at']) {
            $data['active_at'] = $page['active_at'];
        }
        if (isset($page['expires_at']) && $page['expires_at']) {
            $data['expires_at'] = $page['expires_at'];
        }
        Device::whereIn('id', $page['ids'])
            ->update($data);
        return $this->success();
    }

    /**删除
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function del(RequestInterface $request): \Psr\Http\Message\ResponseInterface
    {
        $id = $request->input('id', 0, 'int');
        if (!$id) {
            return $this->error(ErrorCode::PARAMS_ERR);
        }
        $check = Order::where('device_id', $id)->count();
        if ($check > 0) {
            return $this->error(1001, '设备已创收并有相关订单 为保证数据完整性请勿删除');
        }
        $this->device->where('id', $id)->delete();
        return $this->success();
    }

    public function detail(RequestInterface $request): \Psr\Http\Message\ResponseInterface
    {
        $id = $request->input('id', 0, 'int');
        if (!$id) {
            return $this->error(ErrorCode::PARAMS_ERR);
        }
        $data = $this->device->where('id', $id)
            ->with('port')->first();
        return $this->success($data);
    }


    /**复位设备
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function reset(RequestInterface $request): \Psr\Http\Message\ResponseInterface
    {
        $id = $request->input('id', 0, 'int');
        if (!$id) {
            return $this->error(ErrorCode::PARAMS_ERR);
        }
        $device = $this->device->where('id', $id)->first();
        $device->distributor_id = 0;
        $device->station_id = 0;
        try {
            $device->save();
            return $this->success(msg: '复位成功');
        } catch (\Exception $e) {
            return $this->error(msg: $e->getMessage());
        }
    }

    /**
     * 读取设备参数
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function readParams(RequestInterface $request): ResponseInterface
    {
        $id = $request->input('id', 0);
        if (!$id) {
            return $this->error(ErrorCode::PARAMS_ERR);
        }
        try {
            $device = $this->device->query()->where('id', $id)->firstOrFail();
            $data['fd'] = $device->fd;
            $data['sn'] = $device->sn;
            $response = DeviceService::postTcp('/tcp/getParams', $data);
            $responseData = json_decode($response->getBody()->getContents(), true);
            if ($response->getStatusCode() == 200) {
                if ($responseData['code'] == 200) {
                    return $this->success(msg: '读取成功 请稍后刷新列表查看');
                } else {
                    return $this->error(1001, $responseData['msg']);
                }
            } else {
                return $this->error(msg: '读取失败: ' . ($responseData['message'] ?? '未知错误'));
            }
        } catch (\Exception $e) {
            return $this->error(msg: $e->getMessage());
        }
    }

    /**
     * 更新设备参数
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function updateParams(RequestInterface $request): ResponseInterface
    {
        $data = $request->post();
        try {
            $device = $this->device->where('sn', $data['sn'])->first();
            $device->fill($data);
            $device->save();
            $response = DeviceService::postTcp('/tcp/setParams', $data);
            $responseData = json_decode($response->getBody()->getContents(), true);
            if ($response->getStatusCode() == 200) {
                if ($responseData['code'] == 200) {
                    return $this->success(msg: '设置成功 请稍后刷新列表查看');
                } else {
                    return $this->error(1001, $responseData['msg']);
                }
            } else {
                return $this->error(msg: '设置失败: ' . ($responseData['message'] ?? '未知错误'));
            }
        } catch (\Exception $e) {
            return $this->error(msg: $e->getMessage());
        }
    }


    /**开启端口设备
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function startPort(RequestInterface $request): ResponseInterface
    {
        $params = $request->post();
        try {
            // 查找设备
            $device = $this->device->where('sn', $params['sn'])->first();
            if (!$device) {
                return $this->error(1001, '设备不存在');
            }

            // 检查设备在线状态
            if (!$device->fd || $device->inline != 1) {
                return $this->error(1001, '设备未在线');
            }

            Db::beginTransaction();

            // 创建订单
            $number = $this->normal->randOrder($device->id);
            $order = new Order();
            $order->device_id = $device->id;
            $order->sn = $device->sn;
            $order->number = $number;
            $order->status = Order::STATUS_PAID;
            $order->payment_type = Order::ADMIN;
            $order->channel_number = $params['channel_number'];
            $order->station_id = $device->station_id;
            $order->fee = 0;
            $order->minutes = $params['minutes'];
            $order->distributor_id = $device->distributor_id;
            $order->power_fee = $params['fee'];
            $order->save();

            // 准备发送数据
            $post = [
                'fd' => $device->fd,
                'sn' => $device->sn,
                'number' => $number,
                'channel_number' => $params['channel_number'],
                'duration' => (int)($params['minutes'] * 60),
                'power_fee' => (int)($params['fee'] * 100)
            ];

            // 发送TCP请求
            $response = DeviceService::postTcp('/tcp/start', $post);
            $responseData = json_decode($response->getBody()->getContents(), true);
            if ($response->getStatusCode() == 200) {
                if ($responseData['code'] == 200) {
                    Db::commit();
                    return $this->success(msg: '开启成功');
                } else {
                    Db::rollBack();
                    return $this->error(1001, $responseData['msg'] ?? '开启失败');
                }
            } else {
                Db::rollBack();
                return $this->error(1001, '开启失败: ' . ($responseData['message'] ?? '未知错误'));
            }

        } catch (\Exception $e) {
            Db::rollBack();
            return $this->error(1001, '操作异常: ' . $e->getMessage());
        }
    }

    /**重启设备
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function restart(RequestInterface $request)
    {
        try {
            $sn = $request->input('sn');
            $device = $this->device->where('sn', $sn)->first();
            if (!$device) {
                return $this->error(1001, '设备不存在');
            }

            // 检查设备在线状态
            if (!$device->fd || $device->inline != 1) {
                return $this->error(1001, '设备未在线');
            }
            $data = [
                'sn' => $sn,
                'fd' => $device->fd
            ];
            $response = DeviceService::postTcp('/tcp/restart', $data);
            $responseData = json_decode($response->getBody()->getContents(), true);
            if ($response->getStatusCode() == 200) {
                if ($responseData['code'] == 200) {
                    Db::commit();
                    return $this->success(msg: '重启成功');
                } else {
                    Db::rollBack();
                    return $this->error(1001, $responseData['msg'] ?? '重启失败');
                }
            } else {
                Db::rollBack();
                return $this->error(1001, '重启失败: ' . ($responseData['message'] ?? '未知错误'));
            }
        } catch (\Exception $e) {
            return $this->error(1001, '操作异常: ' . $e->getMessage());
        }
    }


    /**根据经销商获取设备
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function distributorDevices(RequestInterface $request): ResponseInterface
    {
        $distributorId = $request->input('distributor_id');
        $data = Station::where('distributor_id', $distributorId)->where('is_active', 1)
            ->get();
        return $this->success($data);
    }

    /**获取最近回传的20条
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getSignalList(RequestInterface $request): ResponseInterface
    {
        $devId = $request->input('device_id');
        $list = DeviceSignalLog::where('device_id', $devId)
            ->orderBy('id', 'desc')
            ->limit(20)
            ->get();
        return $this->success($list);
    }

    /**获取套餐
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getCharge(RequestInterface $request): ResponseInterface
    {
        $station_id = $request->input('station_id');
        $station = Station::find($station_id);
        if (!$station) {
            return $this->error('电站信息不存在');
        }
        if ($station->charge_id <= 0) {
            $charge = ChargeOption::where('distributor_id', 0)
                ->with('time_children', 'power_children', 'service_children')
                ->where('is_del', 1)->first();
        } else {
            $charge = ChargeOption::where('id', $station->charge_id)
                ->with('time_children', 'power_children', 'service_children')->first();
        }
        if (!$charge) {
            return $this->error(1001, '设备暂无可用套餐');
        }

        return $this->success($charge);
    }

}
